package com.inibb.app.global;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.inibb.app.po.SaI18NMsg;
import com.inibb.app.service.admin.II18nMsgService;
import com.inibb.app.util.SecurityUtils;



public class I18nMessagesMapBean implements Map<String, String>,Serializable {

	private static final long serialVersionUID = 1L;

	private Logger logger = LoggerFactory.getLogger(this.getClass());
	
//	@Autowired
//	private II18nMsgService i18nMsgService;

	private Map<String, I18nResourceBundle> bundles;
//	@Autowired
	public void init(II18nMsgService i18nMsgService) {
		bundles = new HashMap<String, I18nResourceBundle>();
		List<String> supportedLocales = new ArrayList<String>();
		supportedLocales.add("en_US");
		supportedLocales.add("zh_CN");
		for (String locale : supportedLocales) {
			logger.trace("constructing i18 msg bundle for locale {}", locale);
			Map<String, String> map = new HashMap<String, String>();
			List<SaI18NMsg> ls = i18nMsgService.getI18nMessagesByLocale(locale);

			for (SaI18NMsg intMsg : ls) {
				String key = StringUtils.trimToEmpty(intMsg.getMtype()) + ":" + StringUtils.trimToEmpty(intMsg.getMkey());
				String val = null;
				if(StringUtils.isEmpty(intMsg.getShortDesp()))
					val = StringUtils.trimToEmpty(intMsg.getLongDesp());
				else
					val = StringUtils.trimToEmpty(intMsg.getShortDesp());
				logger.trace("loading i18 msg to message bundle, key={}, label={}", key, val);
				map.put(key, val);
			}
			I18nResourceBundle bundle = new I18nResourceBundle(locale, map);
			bundles.put(locale, bundle);
		}

	}

	public I18nResourceBundle getI18nResourceBundle(String locale) {
		I18nResourceBundle bundle = null;
		if (bundles != null) {
			bundle = this.bundles.get(locale);
		}
		if (bundle == null) {
			bundle = new I18nResourceBundle(locale, new HashMap<String, String>());
		}
		return bundle;
	}

	public I18nResourceBundle getCurrentI18nResourceBundle() {
		return getI18nResourceBundle( SecurityUtils.getCurrentLocaleString() );
	}

	/*****************************/

	@Override
	public void clear() {
		bundles.clear();
	}

	@Override
	public boolean containsKey(Object key) {
		return getCurrentI18nResourceBundle().containsKey(String.valueOf(key));
	}

	@Override
	public boolean containsValue(Object value) {
		return getCurrentI18nResourceBundle().containsValue(String.valueOf(value));
	}

	@Override
	public Set<java.util.Map.Entry<String, String>> entrySet() {
		return getCurrentI18nResourceBundle().entrySet();
	}

	@Override
	public String get(Object key) {
		String val = getCurrentI18nResourceBundle().get(key);
		if (StringUtils.isEmpty(val)) {
			logger.warn("Can not find message definition for key={}, locale={}", key, getCurrentI18nResourceBundle().getLocale());
		}
		return val;
	}

	public String get(String codeType, String codeId) {
		return get(SecurityUtils.getCurrentLocaleString(), codeType, codeId);
	}
	
	public String get(String locale, String codeType, String codeId) {
		I18nResourceBundle bundle = getI18nResourceBundle(locale);
		String key = StringUtils.trimToEmpty(codeType) + ":" + StringUtils.trimToEmpty(codeId);
		String val = bundle.get( key );
		if (StringUtils.isEmpty(val)) {
			logger.warn("Can not find message definition for key={}, locale={}", codeType + ":" + codeId, bundle.getLocale());
			
			val = StringUtils.EMPTY;
		}
		return val;
	}
	
	public String getWithDefault (String codeType, String codeId, String defaultLabel) {
		return getWithDefault(SecurityUtils.getCurrentLocaleString(), codeType, codeId, defaultLabel);
	}
	
	public String getWithDefault (String locale, String codeType, String codeId, String defaultLabel) {
		I18nResourceBundle bundle = getI18nResourceBundle(locale);
		String key = StringUtils.trimToEmpty(codeType) + ":" + StringUtils.trimToEmpty(codeId);
		String val = bundle.get( key );
		if (StringUtils.isEmpty(val)) {
			logger.warn("Can not find message definition for key={}, locale={}", codeType + ":" + codeId, bundle.getLocale());

			val = defaultLabel;
		}
		return val;
	}
	
	private String getStringFieldValue (Object object, String fieldName) {
		if (null == object && StringUtils.isBlank(fieldName)) {
			return StringUtils.EMPTY;
		}
		
		try {
			return BeanUtils.getProperty(object, fieldName);
		} catch (Exception e) {
			return StringUtils.EMPTY;
		} 
	}

	@Override
	public boolean isEmpty() {
		return getCurrentI18nResourceBundle().isEmpty();
	}

	@Override
	public Set<String> keySet() {
		return getCurrentI18nResourceBundle().keySet();
	}

	@Override
	public String put(String key, String value) {
		return getCurrentI18nResourceBundle().put(key, value);
	}

	@Override
	public void putAll(Map<? extends String, ? extends String> m) {
		getCurrentI18nResourceBundle().putAll(m);
	}

	@Override
	public String remove(Object key) {
		return getCurrentI18nResourceBundle().remove(key);
	}

	@Override
	public int size() {
		return getCurrentI18nResourceBundle().size();
	}

	@Override
	public Collection<String> values() {
		return getCurrentI18nResourceBundle().values();
	}

	public static class I18nResourceBundle implements Map<String, String>, java.io.Serializable  {
		private String locale;
		private Map<String, String> contents = new HashMap<String, String>();

		/**
		 * Creates a new I18nResourceBundle.
		 * 
		 * @param the
		 *            map that containing a set of key value of a specific
		 *            locale.
		 */
		public I18nResourceBundle(String locale, Map<String, String> keyValues) {
			this.contents = keyValues;
			this.locale = locale;
		}

		@Override
		public void clear() {
			this.contents.clear();
		}

		@Override
		public boolean containsKey(Object key) {
			return contents.containsKey(key);
		}

		@Override
		public boolean containsValue(Object value) {
			return contents.containsValue(value);
		}

		@Override
		public Set<Entry<String, String>> entrySet() {
			return this.contents.entrySet();
		}

		@Override
		public String get(Object key) {
			return this.contents.get(key);
		}

		@Override
		public boolean isEmpty() {
			return this.contents.isEmpty();
		}

		@Override
		public String put(String key, String value) {
			return this.contents.put(key, value);
		}

		@Override
		public void putAll(Map<? extends String, ? extends String> m) {
			this.contents.putAll(m);
		}

		@Override
		public String remove(Object key) {
			return this.contents.remove(key);
		}

		@Override
		public int size() {
			return this.contents.size();
		}

		@Override
		public Collection<String> values() {
			return this.contents.values();
		}

		@Override
		public Set<String> keySet() {
			return this.contents.keySet();
		}

		public String getLocale() {
			return locale;
		}
	}
}